﻿using System;

namespace Aeon.Emulator.Decoding
{
    /// <summary>
    /// Allows bytes or words to be read sequentially from an operand stream.
    /// </summary>
    internal struct OperandReader
    {
        #region Constructors
        /// <summary>
        /// Initializes a new OperandReader struct.
        /// </summary>
        /// <param name="data">Operand stream to read from.</param>
        public OperandReader(byte[] data)
        {
            this.data = data;
            this.index = 0;
        }
        #endregion

        #region Public Properties
        /// <summary>
        /// Gets the current position of the reader in bytes.
        /// </summary>
        public int Position
        {
            get { return this.index; }
        }
        #endregion

        #region Public Methods
        /// <summary>
        /// Returns the next byte in the stream.
        /// </summary>
        /// <returns>Next byte in the stream.</returns>
        public byte ReadByte()
        {
            if(index < 0 || index >= data.Length)
                throw new InvalidOperationException();

            return this.data[index++];
        }
        /// <summary>
        /// Returns the next signed byte in the stream.
        /// </summary>
        /// <returns>Next signed byte in the stream.</returns>
        public sbyte ReadSByte()
        {
            return (sbyte)ReadByte();
        }
        /// <summary>
        /// Returns the next signed 16-bit integer in the stream.
        /// </summary>
        /// <returns>Next signed 16-bit integer in the stream.</returns>
        public short ReadInt16()
        {
            return (short)ReadUInt16();
        }
        /// <summary>
        /// Returns the next unsigned 16-bit integer in the stream.
        /// </summary>
        /// <returns>Next unsigned 16-bit integer in the stream.</returns>
        public ushort ReadUInt16()
        {
            if(index < 0 || index >= data.Length - 2)
                throw new InvalidOperationException();

            index += 2;

            return BitConverter.ToUInt16(this.data, index - 2);
        }
        /// <summary>
        /// Return sthe next unsigned 32-bit integer in the stream.
        /// </summary>
        /// <returns>Next unsigned 32-bit integer in the stream.</returns>
        public uint ReadUInt32()
        {
            if(index < 0 || index >= data.Length - 4)
                throw new InvalidOperationException();

            index += 4;

            return BitConverter.ToUInt32(this.data, index - 4);
        }
        #endregion

        #region Private Fields
        private byte[] data;
        private int index;
        #endregion
    }
}
